/*============================================================================*/
/*                        Tortoise Team			                              */
/*============================================================================*/
/*                        OBJECT SPECIFICATION                                */
/*============================================================================*
* C Source:         %APP_RCA_Camera.c%
* Instance:         RPL_1
* %version:         1.0 %
* %created_by:      Andres Torres Garcia %
* %date_created:    Sunday Nov  04 20:38:03 2012 %
*=============================================================================*/
/* DESCRIPTION : C source file for the application of the RCA Camera          */
/*============================================================================*/
/* FUNCTION COMMENT : This file contains the function definitions of the      */
/*					  application layer of the RCA Camera.                    */
/*                                                                            */
/*============================================================================*/
/*                               OBJECT HISTORY                               */
/*============================================================================*/
/*  REVISION |   DATE      |                               |      AUTHOR      */
/*----------------------------------------------------------------------------*/
/*  1.0      | 04/11/2012  |                               | Andres Torres    */
/* Integration under Continuus CM                                             */
/*============================================================================*/

/* Includes */
/* -------- */

#include "HAL_RCA_Camera.h"
#include "APP_RCA_Camera.h"
#include "stdtypedef.h"
#include "HAL_Btn.h"

/* Functions macros, constants, types and datas         */
/* ---------------------------------------------------- */
/* Functions macros */

#define GOAL				42		//0010-1010

#define BLACK_LINE	 		2		//0000-0010
#define BLACK_LINE_2	 	1		//0000-0001 - 2 shifts

#define PAT_LENGHT	10

#define CHAR_BIT 8

/*==================================================*/ 
/* Definition of constants                          */
/*==================================================*/ 


/*======================================================*/ 
/* Definition of RAM variables                          */
/*======================================================*/ 

T_UBYTE ub_bin_pixels[NUM_LINES_CAPTURE][PIXELS_PER_LINE];

T_SWORD sw_Threshold = 0;

T_SWORD sw_max = 0;
T_SWORD sw_min = 1023;

T_UBYTE Can_Process_Pixels = 0;

typedef struct Pattern_info {
	
	T_UBYTE width[20];
	
	T_UBYTE value;
	
	T_UBYTE valid;
	
} Pattern_info;


Line_info line_info[NUM_LINES_CAPTURE];

Pattern_info pat_info[PAT_LENGHT];

T_UBYTE BinValid[NUM_LINES_CAPTURE];

T_UBYTE ub_IsGoal = 0;

extern T_UBYTE ub_TotalPix[NUM_LINES_CAPTURE];

/*======================================================*/ 
/* close variable declaration sections                  */
/*======================================================*/ 

/* Private defines */

/* Private functions prototypes */
/* ---------------------------- */

void vfn_processPixels( T_SWORD us_pixels[], T_UBYTE ub_currLine );
void vfnProcess_Lines(void);
T_UWORD getAbs(T_SWORD num);
void vfn_detectLine(T_UBYTE ub_currLine);
void vfn_binarize( T_SWORD sw_pixels[], T_UBYTE ub_currLine );
void vfn_calibrateThreshold(void);

/* Exported functions prototypes */
/* ----------------------------- */

void APP_vfnInitRCA_Capturing(void);
void APP_vfnCaptuProceLines(void);

void APP_vfnDeselectLine( T_UBYTE line );
void APP_vfnSelectLine( T_UBYTE line );
void APP_vfnSelectPredefLinesToCapture(void);
void APP_vfnStopCapturing(void);
void APP_vfnStartCapturing(void);

/* Inline functions */
/* ---------------- */

/* Private functions */
/* ----------------- */

T_UWORD getAbs(T_SWORD num)
{
	T_SWORD const mask = num >> (sizeof(T_SWORD) * CHAR_BIT - 1);
  	return ((num ^ mask) - mask);
}

/**************************************************************
 *  Name                 : 
 *  Description          :
 *  Parameters           :  [Input, Output, Input / output]
 *  Return               :
 *  Critical/explanation :    No
 **************************************************************/
 
void vfn_calibrateThreshold(void)
{
	T_SWORD sw_tmp = 0;
	
	T_UBYTE i = 0;
	
	sw_max = 0;
	sw_min = 1023;
	
	while( sw_LinePixels[4][i] < 0x64)
	{
		i++;
	}
	
	for(; i < PIXELS_PER_LINE; i++)
	{
	
		if( sw_LinePixels[4][i] < 0x64 )
		{
			break;
		}
	
		if( sw_LinePixels[4][i]  > sw_max )
		{
			sw_max = sw_LinePixels[4][i];
		}
		
		if( sw_LinePixels[4][i]  < sw_min )
		{
			sw_min = sw_LinePixels[4][i];
		}
	}
	
	sw_tmp = sw_max - sw_min;
	
	sw_tmp = sw_tmp / 2;
	
	//sw_Threshold = sw_tmp + sw_tmp / 2;
	
	sw_Threshold = sw_tmp + (6 * sw_tmp) / 7;
}

void vfn_processPixels( T_SWORD sw_pixels[], T_UBYTE ub_currLine )
{
	vfn_binarize( sw_pixels, ub_currLine );
	vfn_detectLine( ub_currLine );
}

void vfn_detectLine(T_UBYTE ub_currLine)
{
	ub_IsGoal = 0;

	if( pat_info[ub_currLine].value ==  GOAL && pat_info[ub_currLine].valid == 7)
	{
		line_info[ub_currLine].leftCorner = pat_info[ub_currLine].width[2];
		line_info[ub_currLine].rightCorner = pat_info[ub_currLine].width[3] - 1;
		
		line_info[ub_currLine].width = pat_info[ub_currLine].width[3] - pat_info[ub_currLine].width[2];
		line_info[ub_currLine].center =  line_info[ub_currLine].width / 2 + pat_info[ub_currLine].width[2];
		
		ub_IsGoal = 1;
	}
	else if( pat_info[ub_currLine].value ==  BLACK_LINE )
	{
		if( pat_info[ub_currLine].valid == 2 )
		{	
			line_info[ub_currLine].leftCorner = 0;
			line_info[ub_currLine].rightCorner = pat_info[ub_currLine].width[0] - 1;
		
			line_info[ub_currLine].width = pat_info[ub_currLine].width[0];
			line_info[ub_currLine].center = line_info[ub_currLine].width / 2;
		}
		else
		{	
			line_info[ub_currLine].leftCorner = pat_info[ub_currLine].width[0];
			line_info[ub_currLine].rightCorner = pat_info[ub_currLine].width[1] - 1;
		
			line_info[ub_currLine].width = pat_info[ub_currLine].width[1] - pat_info[ub_currLine].width[0];
			line_info[ub_currLine].center = line_info[ub_currLine].width / 2 + pat_info[ub_currLine].width[0];
		}
	}
	else if( pat_info[ub_currLine].value ==  BLACK_LINE_2 && pat_info[ub_currLine].valid == 2)
	{
		line_info[ub_currLine].leftCorner = pat_info[ub_currLine].width[0];
		line_info[ub_currLine].rightCorner = pat_info[ub_currLine].width[1] - 1;
		
		line_info[ub_currLine].width = pat_info[ub_currLine].width[1] - pat_info[ub_currLine].width[0];
		line_info[ub_currLine].center = line_info[ub_currLine].width / 2 + pat_info[ub_currLine].width[0];
	}
}

void vfn_binarize( T_SWORD sw_pixels[], T_UBYTE ub_currLine )
{
	T_UBYTE i = 0;
	T_UBYTE j = 0;
	T_UBYTE width = 0;
	
	T_SWORD diff = 0;
	T_SWORD last_diff = 0;
	T_SWORD sw_numComp = 0;
	T_SWORD sw_mierPix = 0;
	T_SWORD sw_abNumb = 0;
	
	pat_info[ub_currLine].value = 0;
	pat_info[ub_currLine].valid = 0;
	pat_info[ub_currLine].width[j] = 0;
	
	while( sw_pixels[i] < 0x64)
	{
		i++;
	}
	
	sw_numComp = sw_pixels[i];
	
	for(;i < ub_TotalPix[ub_currLine]; i++)
	{
		if( sw_pixels[i] < 0x64 )
		{
			break;
		}
		
		width++;
		
		sw_mierPix = sw_pixels[ i ];
		
		diff = sw_numComp - sw_pixels[ i ];
		
		sw_abNumb = getAbs( diff );
		
		if( sw_abNumb >= sw_Threshold )
		{
			last_diff = diff;
			sw_numComp = sw_pixels[i];
			pat_info[ub_currLine].value = pat_info[ub_currLine].value << 1;
			pat_info[ub_currLine].valid++;
			pat_info[ub_currLine].width[j] = width;
			
			j++;
			
			if( diff < 0 )
			{		
				//Adding 1
				pat_info[ub_currLine].value |= 1;
			}
		}
	}
	
	pat_info[ub_currLine].valid++;
	pat_info[ub_currLine].value = pat_info[ub_currLine].value << 1;
	
	if(last_diff > 0)
	{
		//Adding 1
		pat_info[ub_currLine].value |= 1;
	}
	
	pat_info[ub_currLine].width[j] = width;
}

/* Exported functions */
/* ------------------ */

/**************************************************************
 *  Name                 : 
 *  Description          :
 *  Parameters           :  [Input, Output, Input / output]
 *  Return               :
 *  Critical/explanation :    No
 **************************************************************/
void vfnProcess_Lines(void)
{
	T_UBYTE i;

	for( i = 0; i < NUM_LINES_CAPTURE; i++)
	{
		vfn_processPixels(sw_LinePixels[i], i);
	}
}

void APP_vfnStartCapturing(void)
{
	HAL_vfnStartCapturing();
}

void APP_vfnStopCapturing(void)
{
	HAL_vfnStopCapturing();
}

void APP_vfnSelectPredefLinesToCapture(void)
{
	HAL_vfnSelectPredefLinesToCapture();
}

void APP_vfnSelectLine( T_UBYTE line )
{
	HAL_vfnSelectLine( line );
}

void APP_vfnDeselectLine( T_UBYTE line )
{
	HAL_vfnDeselectLine( line );
}

void APP_vfnInitRCA_Capturing(void)
{
	HAL_vfnInitRCA_Capturing();
}

void APP_vfnCaptuProceLines(void)
{
	vfnGetImage();
	
	if( ub_isVertSync && ( ub_LinesCaptured == NUM_LINES_CAPTURE ) )
	{
		if(Can_Process_Pixels == 0)
		{
			vfn_calibrateThreshold();
			
			Can_Process_Pixels = 1;	
		}
		else
		{
			vfnProcess_Lines();
		}
	}
	
	ub_isVertSync = 0;
}